﻿using Autofac;
using Autofac.Core;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Serilog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WCS_Entity.Dto.AutoEquipmentDto;
using WCS_Entity.Model;
using WCS_Service.DomianService.Interface;
using WCS_Service.DomianService.Models;
using WCS_Service.Enums;
using WCS_Service.Services;
using WCS_Utility.Enums;

namespace WCS_Service.DomianService.ComDomainService
{
    /// <summary>
    /// 通信服务管理类
    /// </summary>
    public class ComControl : IComControl
    {
        private readonly IComponentContext _componentContext;

        public event Action<int, ConEquipmentState,string> ConnectEquipmentChange;

        private ConcurrentDictionary<int, IComBaseDomainManage> autoEquipmentComServices { get; set; } = new ConcurrentDictionary<int, IComBaseDomainManage>();

        public ComControl(IComponentContext componentContext)
        {
            _componentContext = componentContext;
        }

        /// <summary>
        /// 服务创建检查
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> ServiceCreateCheckAsync(int id)
        {
            return await Task.Run(() => 
            {
                return autoEquipmentComServices.ContainsKey(id) ? false: true;
            });
        }
        /// <summary>
        /// 创建通信服务
        /// </summary>
        /// <param name="comPara"></param>
        /// <returns></returns>
        public async Task<bool> CreateComServiceAsync(ComInitParaModel comPara, bool isManual)
        {
            try
            {
                if (!_componentContext.TryResolveKeyed<IComBaseDomainManage>(comPara.comType, out IComBaseDomainManage service))
                {
                    Log.Error($"指定的通信类型不支持!");
                    return false;
                }
                service.serviceName = comPara.serviceName;
                service.autoEquipmentId = comPara.AutoEquipmentId;
                service.equipmentType = comPara.equipmentType;
                service.areaCode = comPara.areaCode;
                var comModel = new TcpComParaModel() { ip = comPara.ip, port = comPara.port };
                service.comPara = JsonConvert.SerializeObject(comModel);
                service.protocolPara = comPara.protocolMsgList;
                if (!await service.ConnectAsync())
                {
                    return false;
                }
                service.ComDisConnectEvent += AutoEquipmentDisConnectProcess;
                var value= autoEquipmentComServices.AddOrUpdate(comPara.AutoEquipmentId, service, (key, value) => value);
                if(value is null) return false;
                if (isManual) ConnectEquipmentChange?.Invoke(comPara.AutoEquipmentId,ConEquipmentState.Connect, comPara.equipmentType);
                return true;
            }
            catch (Exception ex)
            {
                Log.Error($"创建通信服务异常{ex.Message}");
                return false;
            }
        }

        public async Task<List<RunAutoEquipmentInfoDto>> GetAllRunServiceInfoAsync()
        {
            List<RunAutoEquipmentInfoDto> result = new List<RunAutoEquipmentInfoDto>();
            List<Task<RunAutoEquipmentInfoDto>> runInfoList = new List<Task<RunAutoEquipmentInfoDto>>();
            foreach (var item in autoEquipmentComServices)
            {
                runInfoList.Add(GetRunServiceInfoAsync(item));
            }
            await Task.WhenAll(runInfoList);
            result = runInfoList.Select(r => r.Result).ToList();
            return result;
        }

        /// <summary>
        /// 暂停指定通信服务
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> RemoveTargetServiceAsync(int id)
        {
            return await Task.Run(() => 
            {
                var flag = autoEquipmentComServices.TryGetValue(id, out var service);
                if (!flag)
                {
                    return false;
                }
                KeyValuePair<int, IComBaseDomainManage> removeValue =
                   new KeyValuePair<int, IComBaseDomainManage>(id, service);
                autoEquipmentComServices.TryRemove(removeValue);
                return true;
            });
        }
        /// <summary>
        /// 根据设备ID查找指定设备的通信服务
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<IComBaseDomainManage> QueryServiceBaseId(int id)
        {
            return await Task.Run(() => 
            {
                var flag = autoEquipmentComServices.TryGetValue(id, out var service);
                if (!flag)
                {
                    return null;
                }
                return service;
            });
        }
        /// <summary>
        /// 根据设备类型和设备编号查找设备的通信服务
        /// </summary>
        /// <param name="eqType"></param>
        /// <param name="eqNumber"></param>
        /// <returns></returns>
        public async Task<IComBaseDomainManage> QueryServiceBaseTypeNumber(string eqType,string eqNumber)
        {
            return await Task.Run(() => 
            {
                var serviceInfo = autoEquipmentComServices.Where(a => a.Value.equipmentType == eqType)
                              ?.FirstOrDefault(e => e.Value.serviceName == eqNumber);
                return serviceInfo?.Value;
            });
        }

        #region private
        /// <summary>
        /// 设备断开连接后处理
        /// </summary>
        /// <param name="id"></param>
        private async Task AutoEquipmentDisConnectProcess(ClientSideDisConnectEventArgs e)
        {
            if (!autoEquipmentComServices.ContainsKey(e.autoEquipmentId))
            {
                return;
            }
            var flag = await RemoveTargetServiceAsync(e.autoEquipmentId);
            if(flag) ConnectEquipmentChange?.Invoke(e.autoEquipmentId, ConEquipmentState.DisConnect, e.equipmentType);
        }

        private async Task<RunAutoEquipmentInfoDto> GetRunServiceInfoAsync(KeyValuePair<int,IComBaseDomainManage> service)
        {
            RunAutoEquipmentInfoDto result = new RunAutoEquipmentInfoDto();
            await Task.Run(() =>
            {
                result.name = service.Value.serviceName;
                result.autoEquipmentId = service.Value.autoEquipmentId;
                result.serviceIp = service.Value.comPara;
                result.equipmentType = service.Value.equipmentType;
                result.areaCode = service.Value.areaCode;
                result.protocolInfo = new Dictionary<string, ProtocolModel>(service.Value.protocolMsgList);
            });
            return result;
        }
        /// <summary>
        /// 判断创建设备是否已经完成连接
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        private bool CreatConnectChecker(int id)
        {
            return autoEquipmentComServices.ContainsKey(id);
        }
        #endregion
    }
}
